package com.lanhai.longheng.impl;
 
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.lanhai.longheng.beans.AgvBean;
import com.lanhai.longheng.beans.AgvDataBean;
import com.lanhai.longheng.dao.AgvDao;
import com.lanhai.longheng.dispatch.AgvCmdMap;
import com.lanhai.longheng.enums.AgvCurrentTransEnum;
import com.lanhai.longheng.enums.AgvMountTypeEnum;
import com.lanhai.longheng.enums.AgvReceiveEnum;
import com.lanhai.longheng.interfaces.IAgv;
import com.lanhai.longheng.interfaces.IAgvMount;
import com.lanhai.longheng.interfaces.IControlArea; 
import com.lanhai.longheng.interfaces.IPower;
import com.lanhai.longheng.interfaces.ITempData;
import com.lanhai.longheng.localized.LHRoadMap;
import com.lanhai.longheng.mapper.AgvMapper;
import com.lanhai.longheng.mapper.DeviceMapper;
import com.lanhai.longheng.utils.Tools; 

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

 
/**
 * 小车协议的实现类
 * 小车bean agvbean_{agvid}:bean
 * 点位与小车 agvdot{dotno}:{agvid}
 * @author zhengwei
 *
 */
@Service 
public class AgvImpl implements IAgv{
	@Autowired
	JedisPool jedisPool;

	@Autowired
	AgvMapper agvMapper;
	@Autowired
	DeviceMapper deviceMapper;
	
	@Autowired
	IPower iPower;
	 
	
	@Autowired
	ITempData iTempData;
	
	@Autowired
	IAgvMount iAgvMount;
	
	@Autowired
	IControlArea iArea; 
	
	@Autowired
	LHRoadMap lhMap;
	
	//缓存，减少从redis中拿数据的可能性
	static Map<Integer,AgvBean> agvMap=  Collections.synchronizedMap(new HashMap<Integer,AgvBean>());
	static Object locker=new Object();

	 private static final Logger agvlog =  LogManager.getLogger("agvlog");
	/**
	 * 从redis中拿小车数据
	 */
	@Override
	public  AgvBean getBean(int agvid) {  
		AgvBean tmp = agvMap.get(agvid);
		if (tmp == null) {
			// 从redis中拿
			synchronized (locker) {
				String key = String.format("agvbean_%d", agvid);
				Jedis jd = jedisPool.getResource();
				String json = jd.get(key);
				Gson gson = new Gson();

				if (json != null && json.isEmpty() == false) {
					try {
						tmp = gson.fromJson(json, AgvBean.class);
					} catch (Exception e) {
						agvlog.error(e);
					}
				}
				if (tmp == null) {
					AgvDao dao = agvMapper.getObj(agvid);
					if (dao != null) {
						tmp = new AgvBean();
						tmp.setAgvId(agvid);
						tmp.setCurrentTrans(AgvCurrentTransEnum.None);
						tmp.setIp(dao.getIp());
						tmp.setPort(dao.getPort());

						json = gson.toJson(tmp);
						// 保存tmp
						jd.set(key, json);
						agvMap.put(agvid, tmp);
					}
				} else {
					agvMap.put(agvid, tmp);
				}
				jd.close();
			}  
		} 
		if(tmp==null) {
			agvlog.error("找不到agvid="+agvid+" 的设备");
			return null;
		}
		return tmp.copy();
	}
 
	
 

	/**
	 *缓存小车数据，同时更新小车点位
	 */
	@Override
	public   void saveCache(  AgvBean bean ) { 
		AgvBean old=getBean(bean.getAgvId());
		agvMap.put(bean.getAgvId(), bean);
		 
		if(notTheSame(old, bean)) { 
			synchronized (locker) {  
				String key=String.format("agvbean_%d", bean.getAgvId());
				Gson gson=new Gson();
				String json=gson.toJson(bean);
				Jedis jd=jedisPool.getResource(); 
				jd.set(key,json);
				jd.close();
			}
		} 
		 
	}
	
	boolean notTheSame(AgvBean o1,AgvBean o2) { 
		if(o1==null) return true;
		if(o1.getAgvId()!=o2.getAgvId()) return true;
		if(o1.getAreaId()!=o2.getAreaId()) return true;
		if(o1.getCurrentTrans()!=o2.getCurrentTrans()) return true;
		if(o1.getNextDeviceid()!=o2.getNextDeviceid()) return true; 
		if(o1.getNextNode()!=o2.getNextNode()) return true; 
		if(o1.getNextProcess()!=o2.getNextProcess()) return true; 
		if(o1.getSpecialline()!=o2.getSpecialline()) return true; 
		if(o1.isFinishTrans()!=o2.isFinishTrans()) return true;  
		if(o1.isUpHasTrans()!=o2.isUpHasTrans()) return true;  
		if(o1.isDownHasTrans()!=o2.isDownHasTrans()) return true;  
		return false;
	}

	
	/**
	 *分析小车上报数据
	 */
	@Override
	public AgvDataBean analyseData(byte[] data) {
		if (data.length < 14) {
			return null;
		}
		if(data[0]!=-95) {
			return null;
		}
		//A1 0E   02 00   00 01   F2 0D   05 02   00 64 1C 00 00 
		AgvDataBean obj = new AgvDataBean();
		obj.setAgvId(data[1]);
		obj.setCmdStr(Tools.byte2HexStr(data));
		if (data[10] == 1) {
			// 小车异常
			obj.setReceiveType(AgvReceiveEnum.ERR);
			return obj;
		}  
		obj.setReceiveType(AgvReceiveEnum.getAgvReceiveEnumByCode(data[2]));
		byte[] tmp=new byte[]{ data[3], data[4], 0, 0 }; 
		obj.setRoad(Tools.toIntL(tmp));
		
		if (data[12] == 0x00) {
			// 全空
			obj.setUpFull(false);
			obj.setDownFull(false);
			obj.setMountType(AgvMountTypeEnum.AllEmpty); 
		} else if (data[12] == 0x01) {
			// 上空下满
			obj.setUpFull(false);
			obj.setDownFull(true);
			obj.setMountType(AgvMountTypeEnum.UpEmptyAndDownFull); 
		} else if (data[12] == 0x10) {
			// 上满下空
			obj.setUpFull(true);
			obj.setDownFull(false);
			obj.setMountType(AgvMountTypeEnum.UpFullAndDownEmpty); 
		} else if (data[12] == 0x11) {
			// 全满
			obj.setUpFull(true);
			obj.setDownFull(true);
			obj.setMountType(AgvMountTypeEnum.AllFull); 
		}else {
			// 0x20  0x02 0x22一类的异常
			obj.setMountType(AgvMountTypeEnum.Error);
		}
		obj.setPower(data[11]);
		 
		byte[] gpX = { data[6], data[7], 0, 0 };
		byte[] gpY = { data[8], data[9], 0, 0 };
		obj.setX(Tools.toIntL(gpX));
		obj.setY(Tools.toIntL(gpY));
		
		obj.setData(data);
		return obj;
	}




	@Override
	public void reset(int agvid) {
		AgvBean tmp = agvMap.get(agvid);
		if(tmp!=null) {
			tmp.setFinishTrans(false);
			tmp.setUpHasTrans(false);
			tmp.setDownHasTrans(false);
			tmp.setLastCmd("");
			tmp.setCmdtime(0);
			
			//传输关闭
			AgvCmdMap.setTransing(agvid, false); 

			//窄路去掉
			lhMap.clearAgv(agvid);
			
			//更新agv状态
			synchronized (locker) {  
				String key=String.format("agvbean_%d", tmp.getAgvId());
				Gson gson=new Gson();
				String json=gson.toJson(tmp);
				Jedis jd=jedisPool.getResource(); 
				jd.set(key,json);
				jd.close();
			}
		}
		
		
		
	}
 
	
 
}
